package num

import (
	"math"
	"math/big"
	"testing"
)

func TestIntegerRNEG(t *testing.T) {
	tests := []struct {
		name     string
		input    Integer
		expected Integer
	}{
		{"Positive integer", Integer(5), Integer(-5)},
		{"Negative integer", Integer(-3), Integer(3)},
		{"Zero", Integer(0), Integer(0)},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			result := tt.input.RNEG()
			if result.Type() != INTEGER_TYPE {
				t.Fatalf("Expected INTEGER_TYPE, got %v", result.Type())
			}
			intResult := result.(Integer)
			if intResult != tt.expected {
				t.Fatalf("Expected %v, got %v", tt.expected, intResult)
			}
		})
	}
}

func TestRationalRNEG(t *testing.T) {
	tests := []struct {
		name     string
		input    Rational
		expected Rational
	}{
		{"Positive rational", Rational(*big.NewRat(3, 4)), Rational(*big.NewRat(-3, 4))},
		{"Negative rational", Rational(*big.NewRat(-2, 5)), Rational(*big.NewRat(2, 5))},
		{"Negative denominator", Rational(*big.NewRat(3, -4)), Rational(*big.NewRat(3, 4))},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			result := tt.input.RNEG()
			if result.Type() != RATIONAL_TYPE {
				t.Fatalf("Expected RATIONAL_TYPE, got %v", result.Type())
			}
			ratResult := result.(Rational)
			if (*big.Rat)(&ratResult).Cmp((*big.Rat)(&tt.expected)) != 0 {
				t.Fatalf("Expected %s, got %s", (*big.Rat)(&tt.expected).String(), (*big.Rat)(&ratResult).String())
			}
		})
	}
}

func TestRealRNEG(t *testing.T) {
	tests := []struct {
		name     string
		input    Real
		expected Real
	}{
		{"Positive real", Real(3.14), Real(-3.14)},
		{"Negative real", Real(-2.5), Real(2.5)},
		{"Zero", Real(0.0), Real(0.0)},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			result := tt.input.RNEG()
			if result.Type() != REAL_TYPE {
				t.Fatalf("Expected REAL_TYPE, got %v", result.Type())
			}
			realResult := result.(Real)
			if math.IsNaN(float64(tt.expected)) {
				if !math.IsNaN(float64(realResult)) {
					t.Fatalf("Expected NaN, got %v", realResult)
				}
			} else if float64(realResult) != float64(tt.expected) {
				t.Fatalf("Expected %v, got %v", tt.expected, realResult)
			}
		})
	}
}
